import os
import random
import string
import platform
import guizero


class Data(guizero.PushButton):
    type = "整数"
    up = 0
    down = 100
    n = 100
    end = " "
    value = 0


class Maker:
    def __init__(self):
        self.path = ""
        self.cnt = 0
        app = guizero.App(title="数据生成器", bg="white", width=1200, height=700)
        guizero.Text(app, "欢迎使用数据生成器", size=30)
        guizero.Box(app, border=1, width="fill")
        master = guizero.Box(app, layout="grid")
        ans_box = guizero.Box(master, grid=[0, 0], align="top")
        box = guizero.Box(ans_box, layout="grid")
        self.select_folder = guizero.PushButton(
            box, text="选择数据文件保存目录", command=self.choose, grid=[0, 0]
        )
        self.path_text = guizero.TextBox(
            box, grid=[1, 0], width=40, height=2, multiline=True
        )
        self.path_text.value = os.path.join(os.path.dirname(__file__), "test")
        self.path = self.path_text.value.strip()
        box = guizero.Box(ans_box, layout="grid")
        guizero.Text(box, "文件名起始", grid=[0, 0])
        self.a = guizero.TextBox(
            box, text="1", grid=[1, 0], width=10, height=1, multiline=True
        )
        guizero.Text(box, "文件名结束", grid=[2, 0])
        self.b = guizero.TextBox(
            box, text="10", grid=[3, 0], width=10, height=1, multiline=True
        )
        guizero.Text(box, "前缀", grid=[4, 0])
        self.left = guizero.TextBox(
            box, text=" ", grid=[5, 0], width=10, height=1, multiline=True
        )

        # 已添加数据
        guizero.Text(ans_box, "已添加变量")
        self.datas = []
        self.datas_box = guizero.Box(ans_box, layout="grid", align="top")

        # 分割线
        guizero.Box(master, grid=[1, 0], width=1, align="top", height=150, border=1)
        # 添加一个变量
        data_format_box = guizero.Box(master, grid=[2, 0], align="top")
        guizero.Text(data_format_box, "变量格式")
        box = guizero.Box(data_format_box, layout="grid")
        guizero.Text(box, "变量名", grid=[0, 0])
        data_format_box.name = guizero.TextBox(box, text="n", grid=[1, 0])

        box = guizero.Box(data_format_box, layout="grid")
        guizero.Text(box, "下限", grid=[0, 0])
        data_format_box.down = guizero.TextBox(box, text="1", grid=[1, 0])
        guizero.Text(box, "上限", grid=[2, 0])
        data_format_box.up = guizero.TextBox(box, text="100", grid=[3, 0])
        guizero.Text(box, "数据类型", grid=[4, 0])
        data_format_box.type = guizero.Combo(
            box,
            options=["整数", "浮点数", "大写字母", "小写字母", "大小写字母", "字母数字下划线", "可打印"],
            selected="整数",
            grid=[5, 0],
        )

        guizero.Text(box, "数量", grid=[0, 1])
        data_format_box.n = guizero.TextBox(box, text="1", grid=[1, 1])
        guizero.Text(box, "间隔", grid=[2, 1])
        data_format_box.end = guizero.TextBox(box, text=" ", grid=[3, 1])
        guizero.PushButton(box, command=self.add_one, text="添加变量", grid=[4, 1], pady=2)
        guizero.PushButton(box, command=self.endl, text="添加换行", grid=[5, 1], pady=2)

        # 数据预览和答案
        guizero.Box(app, border=1, width="fill")
        box = guizero.Box(app, layout="grid", align="top")
        guizero.Text(box, "数据预览", grid=[0, 0])
        guizero.Text(box, "CPP答案", grid=[1, 0])
        self.preview = guizero.TextBox(
            box, width=45, multiline=True, height=10, scrollbar=True, grid=[0, 1, 1, 1]
        )
        self.answer = guizero.TextBox(
            box, width=45, multiline=True, height=10, scrollbar=True, grid=[1, 1, 1, 1]
        )

        # 保存
        box = guizero.Box(app, layout="grid", align="top")
        guizero.PushButton(box, self.del_data, text="清空数据", grid=[0, 2])
        guizero.PushButton(box, self.del_ans, text="清空答案", grid=[1, 2])
        guizero.PushButton(box, self.save_data, text="保存数据", grid=[2, 2])

        self.app = app
        self.data_format = data_format_box
        app.display()

    def choose(self):
        """
        选择目录
        """
        self.path = guizero.select_folder(title="选择数据文件保存目录")
        self.path_text.value = self.path

    def save_data(self):
        """保存数据"""
        a = self.a.value
        a = int(a)
        b = self.b.value
        b = int(b)
        b += 1
        for i in range(a, b):
            datas = ""
            for data in self.datas:
                datas += self.create_values(data)
            self.preview.value = datas
            name = f"{self.left.value.strip()}{i}.in"
            file = os.path.join(self.path, name)
            if not os.path.isdir(self.path):
                os.makedirs(self.path)
            with open(file, "w", encoding="utf-8") as f:
                f.write(datas)
        self.save_ans()

    def add_one(self):
        """增加一个变量到系统里"""
        data = Data(
            self.datas_box,
            text=self.data_format.name.value,
            grid=[self.cnt % 8, self.cnt // 8],
        )
        self.datas.append(data)
        self.cnt += 1
        data.type = self.data_format.type.value
        data.up = self.data_format.up.value
        data.down = self.data_format.down.value
        data.n = self.data_format.n.value
        if(self.data_format.end.value):
            data.end = self.data_format.end.value[0]
        else:
            data.end=''
        temp_string =self.preview.value + self.create_values(data)
        if len(temp_string)>1000:
            temp_string=temp_string[:1000]+"……"
        self.preview.value = temp_string

    def endl(self):
        """增加换行"""
        data = Data(
            self.datas_box,
            text=self.data_format.name.value,
            grid=[self.cnt % 8, self.cnt // 8],
        )
        self.datas.append(data)
        self.cnt += 1
        data.type = "换行"
        data.text = "换行"
        self.preview.value = self.preview.value + self.create_values(data)

    def create_values(self, data):
        """根据变量创建数据"""
        d_type = data.type
        up = data.up
        down = data.down
        n = data.n
        end = data.end
        flag = 0
        x = y = ""
        if isinstance(n, str) and "*" in n:
            x = n.split("*")[0]
            y = n.split("*")[1]
            for d in self.datas:
                if d.text == x:
                    x = d.value
                if d.text == y:
                    y = d.value
                if x != "" and y != "":
                    break
            x = int(x)
            y = int(y)
            n = x * y
            flag = 1
        if isinstance(n, str):
            for d in self.datas:
                if d.text == n:  # 如果用别的数据生成的n
                    n = d.value
                    break

        n = int(n)
        up = int(up)
        down = int(down)
        values = ""

        if "换行" in d_type:
            return "\n"

        def create_one_value():
            if "整数" in d_type:
                value = random.randint(down, up)
            elif "浮点数" in d_type:
                value = random.random()
                value = value * (up - down) + down
            elif "大写" in d_type:
                times = random.randint(down, up)
                value = "".join(random.choices(string.ascii_uppercase, k=times))
            elif "小写" in d_type:
                times = random.randint(down, up)
                value = "".join(random.choices(string.ascii_lowercase, k=times))
            elif "大小写" in d_type:
                times = random.randint(down, up)
                value = "".join(random.choices(string.ascii_letters, k=times))
            elif "字母数字" in d_type:
                times = random.randint(down, up)
                strings = random.choices(
                    string.ascii_letters + string.digits + "_", k=times
                )
                value = "".join(strings)
            elif "可打印" in d_type:
                times = random.randint(down, up)
                value = "".join(random.choices(string.printable, k=times))
            return str(value) + end

        for i in range(n):
            values += create_one_value()
            if flag and (i + 1) % x == 0:
                values += "\n"
        data.value = values
        return values

    def del_data(self):
        """清空变量"""
        for data in self.datas:
            data.destroy()
        self.datas = []
        self.cnt = 1
        self.preview.value = ""

    def del_ans(self):
        """清空答案"""
        self.answer.value=""

    def save_ans(self):
        """加载和保存答案"""
        cpp_code = self.answer.value
        if "include" in cpp_code:
            guizero.info("提示", "输入生成完毕，点击确认开始生成输出。")
            a = self.a.value
            a = int(a)
            b = self.b.value
            b = int(b)
            b += 1
            file=os.path.join(self.path,"temp.cpp")
            with open(file, "w") as f:
                f.write(cpp_code)            
            if "Linux" in platform.system():
                os.system(f"cd {self.path} && g++ ./temp.cpp -o ./temp -std=c++14 -O2")
                for i in range(a, b):
                    in_name=os.path.join(self.path,f"{i}.in")
                    out_name=os.path.join(self.path,f"{i}.out")
                    os.system(f"cd {self.path} && ./temp < {in_name} > {out_name}")
                os.system(f"cd {self.path} && rm -rf test.zip && zip test.zip ./*")
                guizero.info("提示", "数据生成并打包完毕，谢谢使用！")
            else:
                os.system(f"cd {self.path} && g++ .\\temp.cpp -o .\\temp.exe -std=c++14 -O2")
                for i in range(a, b):
                    in_name=os.path.join(self.path,f"{i}.in")
                    out_name=os.path.join(self.path,f"{i}.out")
                    os.system(f"cd {self.path} && .\\temp.exe < {in_name} > {out_name}")
                guizero.info("提示", "数据生成完毕，请手动打包，谢谢使用！")
        else:
            guizero.info("提示", ".in文件生成完毕，请手动打包，谢谢使用！")


if __name__ == "__main__":
    app = Maker()
